package org.visionlibrary.image.filters.thresholding;

import java.awt.Point;

import javax.media.jai.TiledImage;

import org.visionlibrary.image.model.WindowFilter;


/*
 * 1) Savakis A.E. (1998) "Adaptive Document Image Thresholding Using Foreground 
 * and Background Clustering" Proc. of the IEEE Int. Conf. on Image Processing,
 * 3: 785-789
 * http://www.ce.rit.edu/~savakis/papers/ICIP98_savakis.pdf
 * 2) Duc D.A., Du T.L.H., and Duan T.D. (2004) "Optimizing Speed for Adaptive Local 
 * Thresholding Algorithm Using Dynamic Programming" 2004 Int. Conf. on Electronics, 
 * Information, and Communications
 * http://www.fit.hcmuns.edu.vn/~daduc/files/iceic04.pdf
 */
public class SimpleSavakisThreshold extends WindowFilter {
	protected int width = 9;
	protected int height = 9;
	protected int global_threshold = 128; // for 16bpc this isint true

	protected int foreground = 0; // foreground pixel value (default 0)
	protected int background = 255; // background pixel value (default 255 for
	// 8bpc image)

	public SimpleSavakisThreshold() {
		this(9,9,128);
	}
	
	public SimpleSavakisThreshold(int width, int height, int global_threshold) {
		this.width = width;
		this.height = height;
		this.global_threshold = global_threshold;
	}

	public SimpleSavakisThreshold(int width, int height, int global_threshold,
			int foreground, int background) {
		this.width = width;
		this.height = height;
		this.global_threshold = global_threshold;
		this.foreground = foreground;
		this.background = background;
	}

	@Override
	protected int getNewPixelVal(TiledImage src, Point p, int channel) {
		int num_back = 0; /* number of background pixels in a particular window */
		int num_fore = 0; /* number of foreground pixels in a particular window */
		int sum_back = 0; /* sum of background pixels in a particular window */
		int sum_fore = 0; /* sum of foreground pixels in a particular window */

		double mean_back = 0; /*
							 * mean of the background pixels in a particular
							 * window
							 */
		double mean_fore = 0; /* mean of the foreground pixels in a particular window */

		Point pIter = new Point();
		for (pIter.y = 0; pIter.y < windowHeight; pIter.y++)
			for (pIter.x = 0; pIter.x < windowWidth; pIter.x++) {
				int val = getWindowPixelVal(src, pIter, channel);
				if (val <= global_threshold) {
					sum_back += val;
					num_back++;
				} else {
					sum_fore += val;
					num_fore++;
				}
			}
		mean_back = (num_back == 0 ? 0.0 : ( sum_back / ( double ) num_back ) );
	    mean_fore = (num_fore == 0 ? 0.0 : ( sum_fore / ( double ) num_fore ) );

	    /* Calculate the local threshold */
	    double local_threshold = 0.5 * (mean_back + mean_fore);

	    /* Determine the output pixel value */
	    return  ((getWindowPixelVal(src, dstPointInWindow, channel) > local_threshold ) ? foreground : background);
	}

	@Override
	protected void setWindowProperties() {
		windowWidth = width;
		windowHeight = height;
		dstPointInWindow = new Point(width / 2, height / 2);
	}
}
